#include "path.h" 
#include "printSyslog.h"
//边界条件暂默认满足
static int stackPush(pathStack_t* ppathStack, char* data){
    memcpy(ppathStack->pathArr[ppathStack->top],data,strlen(data));
    ppathStack->top++;
    return 0;
}

//边界条件暂时默认满足
static int stackPop(pathStack_t* ppathStack){
    if(ppathStack->top==0){
        return -1;
    }
    memset(ppathStack->pathArr[ppathStack->top-1],0,64);
    ppathStack->top--;
    return 0;
}

static int sendResult(char* data,int netfd){
    train_t train;
    int total =strlen(data);
    int cur = 0;
    while(total-cur >= 1000){
        memset(&train,0,sizeof(train_t));
        train.flag=ISRESULT;
        train.length=1000;
        memcpy(train.data,data+cur,1000);
        send(netfd,&train,sizeof(train_t),0);
        cur+=1000;
    }
    if(total>cur){
        memset(&train,0,sizeof(train_t));
        train.flag=ISRESULT;
        train.length = total - cur;
        memcpy(train.data,data+cur,train.length);
        send(netfd,&train,sizeof(train_t),0);
    }
    return 0;
}

int getCwd(const pathStack_t* ppathStack, char* path){
    if(ppathStack->top==0) return 0;
    char* p = path;
    for(int i = 0 ; i < ppathStack->top-1 ; i++ ){
       /* memcpy(p,ppathStack->pathArr[i],strlen(ppathStack->pathArr[i]));
        p+=strlen(ppathStack->pathArr[i]);
        *p='/';
        p++;*/
        strcat(path,ppathStack->pathArr[i]);
        strcat(path,"/");
    }
    //memcpy(p,ppathStack->pathArr[ppathStack->top-1],strlen(ppathStack->pathArr[ppathStack->top-1]));
   // printf("%s, top=%d\n",ppathStack->pathArr[ppathStack->top-1],ppathStack->top);
    strcat(path,ppathStack->pathArr[ppathStack->top-1]);
    //printf("%s\n",path);
    return 0;
}

static int getList(const char* realPath, char* result){
    char* cur = result;
    DIR* dp = opendir(realPath);
    ERROR_CHECK(dp, NULL, "opendir");
    struct dirent* pdirent = NULL;
    struct stat dirstat;
    while ((pdirent = readdir(dp)) != NULL) {
        char path[1024] = { 0 };
        sprintf(path, "%s/%s", realPath, pdirent->d_name);
        if(strcmp(".",pdirent->d_name)==0 || strcmp("..",pdirent->d_name)==0){
            continue;
        }
        stat(path, &dirstat);
        int c;
        switch (dirstat.st_mode & S_IFMT) {
        case S_IFBLK:  c = 'b'; break;
        case S_IFCHR:  c = 'c'; break;
        case S_IFDIR:  c = 'd'; break;
        case S_IFIFO:  c = 'p'; break;
        case S_IFLNK:  c = 'l'; break;
        case S_IFREG:  c = '-'; break;
        case S_IFSOCK: c = 's'; break;
        default:       c = '?'; break;
        }
        sprintf(cur,"%c", c);
        for(int i=0;i<3;i++){
            if(*cur=='\0'){
                *cur=' ';
            }
            cur++;
        }
        sprintf(cur,"%ld ", dirstat.st_size);
        for(int i=0;i<12;i++){
            if(*cur=='\0'){
                *cur=' ';
            }
            cur++;
        }
        struct tm* ptime;
        ptime = localtime(&dirstat.st_mtime);
        sprintf(cur,"%d月 %d日 %d:%d ", ptime->tm_mon + 1, ptime->tm_mday, ptime->tm_hour, ptime->tm_min);
        for(int i=0;i<18;i++){
            if(*cur=='\0'){
                *cur=' ';
            }
            cur++;
        }
        sprintf(cur,"%s", pdirent->d_name);
        cur+=strlen(pdirent->d_name);
        sprintf(cur,"\n");
        cur++;
    }
    *cur='\0';
    cur++;
    *cur='\n';
    return 0;
}

int pathStackInit(pathStack_t* ppathStack){
    memset(ppathStack->pathArr,0,sizeof(pathStack_t));
    return 0;
}

int changeDir(cmd_t* pcmd, pathStack_t* ppathStack, int netfd,char* pathBase){
    PRINT_LOG(NULL, 0, "cd");
    char target[256];
    memset(target,0,256);
    memcpy(target,pcmd->parameter1,strlen(pcmd->parameter1));
    //printf("target = %s\n",target);
    if(strcmp("..",target)==0){
        //printf("try to cd ..\n");
        //printf("&&top=%d\n",ppathStack->top);
       int ret= stackPop(ppathStack);
       if(ret == -1){
            char result[] = "Already in the root directory!\n";
     //       printf("%s",result);
            sendResult(result,netfd);
       }
       return 0;
    }
    char realPath[256]={0};
    //sprintf(realPath,"/home/54th/netdisk/user1/");
    strcat(realPath,pathBase);
    getCwd(ppathStack,realPath+strlen(pathBase));
    if(ppathStack->top!=0){
        strcat(realPath,"/");
    }
    strcat(realPath,target);
   // printf("targerPath=%s",realPath);
    //printf("--\n");
    if(access(realPath,0)==-1){
        char result[]="The directory does not exist!\n";
   //     printf("%s",result);
        sendResult(result,netfd);
        return -1;
    }
    //printf("The directory exists!\n");
    //printf("try to cd target. top=%d\n",ppathStack->top);
    stackPush(ppathStack, target);
    //printf("%s, top=%d\n",ppathStack->pathArr[ppathStack->top-1],ppathStack->top);
    return 0;
}

int printWokringDir(const pathStack_t* ppathStack, int netfd){
    PRINT_LOG(NULL, 0, "pwd");
    char path[256]={0};
    path[0]='/';
    getCwd(ppathStack,path);
    strcat(path,"\n");
    //printf("cwd:%s",path);
    sendResult(path,netfd);
    return 0;
}

int listFile(const pathStack_t* ppathStack, int netfd,char* pathBase){
    PRINT_LOG(NULL, 0, "ls");
    printf("%s, top=%d\n",ppathStack->pathArr[ppathStack->top-1],ppathStack->top);
    char realPath[256]={0};
    char result[32768]={0};
    for(int i = 0;i<32768;i++){
        result[i]=' ';
    }
    //sprintf(realPath,"/home/54th/netdisk/user1/");
    strcat(realPath,pathBase);
    getCwd(ppathStack,realPath+strlen(pathBase));
    //printf("realcwd: %s\n",realPath);
    getList(realPath,result);
    //printf("%s",result);
    sendResult(result,netfd);
    return 0;
}
